package main

import (
	"flag"
	"fmt"
	"io"
	"net"
	"os"
)

type Client struct {
	ServerIp   string
	ServerPort int
	Conn       net.Conn
	Name       string
	Model      int
}

var serverIp string
var serverPort int

func NewClient(serverIp string, serverPort int) *Client {
	client := Client{
		ServerIp:   serverIp,
		ServerPort: serverPort,
		Model:      -1,
	}
	url := fmt.Sprintf("%s:%d", serverIp, serverPort)
	conn, err := net.Dial("tcp", url)
	if err != nil {
		fmt.Println("dial "+url+"error : ", err)
		return nil
	}
	client.Conn = conn
	return &client
}

func init() {
	// 绑定命令行参数  如 ./client -ip 127.0.0.1 -port 1234
	flag.StringVar(&serverIp, "ip", "127.0.0.1", "服务器ip地址 默认127.0.0.1")
	flag.IntVar(&serverPort, "port", 1234, "服务器端口 默认1234")
	// 参数解析
	flag.Parse()
}

func (client *Client) readModel() bool {
	fmt.Println("1.公聊模式")
	fmt.Println("2.私聊模式")
	fmt.Println("3.更新名称")
	fmt.Println("0.退出")
	var modelReaded int
	fmt.Scanln(&modelReaded)
	if modelReaded >= 0 && modelReaded <= 3 {
		client.Model = modelReaded
		return true
	} else {
		fmt.Println("请输入正确的指令")
		return false
	}
}

func (client *Client) start() {
	for client.Model != 0 {
		// 循环读取 直到读取到正确的值
		for !client.readModel() {
		}
		// go语言的switch break没有fallthough时，使用break和不使用break没有啥区别
		// 使用fallthrough时 会且仅会执行后一个case
		switch client.Model {
		case 1:
			client.publicSendMsg()
			//fallthrough
		case 2:
			client.privateSendMsg()
		case 3:
			client.updateName()
		case 0:
			return
		}
		// 这一块就是协议封装
	}
}

func (client *Client) publicSendMsg() {
	line := ""
	for {
		fmt.Println("请输入消息，exit退出：")
		fmt.Scanln(&line)
		if line == "exit" {
			return
		}
		if len(line) != 0 {
			sendMsg := line + "\n"
			_, err := client.Conn.Write([]byte(sendMsg))
			if err != nil {
				fmt.Println("publicSendMsg err : ", err)
				return
			}
		}
	}
}

func (client *Client) privateSendMsg() {
	toUser := ""
	line := ""
	for toUser != "bye" {
		fmt.Println(">>>>>>在线用户列表：")
		client.selectOnlineUsers()
		fmt.Println(">>>>>>请在填写对方用户名，bye退出：")
		fmt.Scanln(&toUser)
		if toUser == "bye" {
			return
		}
		for {
			fmt.Println("请输入消息，exit退出：")
			fmt.Scanln(&line)
			if line == "exit" {
				// 内部不应该直接退出整个函数  应该还可以和其他用户私聊
				break
			}
			if len(line) != 0 {
				sendMsg := "to|" + toUser + "|" + line + "\n"
				_, err := client.Conn.Write([]byte(sendMsg))
				if err != nil {
					fmt.Println("publicSendMsg err : ", err)
					return
				}
			}
		}
	}
}

func (client *Client) updateName() {
	fmt.Println("请输入新用户名：")
	fmt.Scanln(&client.Name)
	protol := "rename|" + client.Name + "\n"
	_, err := client.Conn.Write([]byte(protol))
	if err != nil {
		fmt.Println("更新用户名失败")
	}
	fmt.Println("更新用户名成功")
}

func (client *Client) printServerResponse() {
	// copy内部是for循环read的 不断的读
	io.Copy(os.Stdout, client.Conn)
}

func (client *Client) selectOnlineUsers() {
	msg := "users\n"
	_, err := client.Conn.Write([]byte(msg))
	if err != nil {
		fmt.Println("查询在线用户失败")
	}
}

func main() {
	client := NewClient(serverIp, serverPort)
	if client == nil {
		fmt.Println(">>>>服务器连接失败")
		return
	}
	fmt.Println(">>>>服务器连接成功")
	// 监听服务器响应并打印
	go client.printServerResponse()

	client.start()
}
